#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/wait.h>

bool Daemon()
{
    // 1.创建子进程，使子进程成为孤儿进程
    pid_t pid = fork();
    if (pid < 0)
    {
        return false;
    }
    else if (pid > 0)
    {
        exit(0);
    }

    // 2.创建新的会话
    pid_t sid = setsid();
    if (sid < 0)
    {
        return false;
    }

    // 3.屏蔽SIGHUP信号，防止因为脱离终端时被结束进程
    signal(SIGHUP, SIG_IGN);

    // 4.再次创建子进程，关闭父进程，子进程不是会话首进程，无控制终端的权限
    pid = fork();
    if (pid < 0)
    {
       return false;
    }
    else if (pid > 0)
    {
        exit(0);
    }

    // 5.设置权限掩码
    umask(0);

    // 6.切换工作目录到根目录下
    if (chdir("/") < 0)
    {
        return false;
    }

    // 7.关闭标准输入，标准输出，标准错误
    close(0);
    close(1);
    close(2);

    // 8.将标准输入，标准输入，标准错误重定向到/dev/null文件中
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_RDWR);
    open("/dev/null", O_RDWR);

    return true;
}

void handler(int signum)
{
    waitpid(-1,nullptr,0);
    pid_t pid=fork();
    if(pid<0)
    {
        exit(1);
    }
    else if(pid==0)
    {
        execl("/home/JK/Linux/Daemon/test","./test",nullptr);
    }
}

int main()
{
    //1.创建守护进程
    bool flag=Daemon();
    if(!flag)
    {
        exit(1);
    }

    //3.自动捕捉SIGCHLD
    struct sigaction act,oldact;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);
    act.sa_handler=handler;
    sigaction(SIGCHLD,&act,&oldact);

    //2.拉起进程
    pid_t pid=fork();
    if(pid<0)
    {
        exit(2);
    }
    else if(pid==0)
    {
        //程序替换
        execl("/home/JK/Linux/Daemon/test","./test",nullptr);
    }

    //父进程就死循环,收到信号就去处理SIGCHLD信号
    printf("father:%d\n",getpid());
    while(true)
    {

    }

    return 0;
}
